/* This code generates the precomputation tables stored in the table/ directory.

   To (re)generate tables:

   1. Check Local.mk, uncomment the line:
      $(call make-unit-test,fd_curve25519_tables,fd_curve25519_tables,fd_ballet fd_util)

   2. Compile for each target backend, this will create a unit-test called fd_curve25519_tables
      $ MACHINE=linux_gcc_icelake make -j
      $ MACHINE=linux_gcc_noarch64 make -j

   3. Run the scripts:
      $ ./build/linux/gcc/icelake/unit-test/fd_curve25519_tables
      $ ./build/linux/gcc/noarch64/unit-test/fd_curve25519_tables

   4. Commit the changes. */

#include "../fd_ballet.h"
#include "fd_curve25519.h"
#include "fd_ristretto255.h"
#include "../hex/fd_hex.h"

#include <stdio.h>

#define STDOUT 0

void
field_constant( FILE * file, char const * name, fd_f25519_t * value ) {
  uchar buf[32];
  char hex[65]; hex[64] = 0;

  fd_hex_encode( hex, fd_f25519_tobytes( buf, value ), 32 );
  fprintf( file, "// 0x%s\n", hex);
  fprintf( file, "static const fd_f25519_t %s[1] = {{\n", name);

  fprintf( file, "  { ");

#if FD_HAS_AVX512
  for( int i=0; i<6; i++ ) {
    fprintf( file, "0x%016lx, ", value->el[i]);
  }
  fprintf( file, "0x0, 0x0, ");
#else
  for( int i=0; i<5; i++ ) {
    fprintf( file, "0x%016lx, ", value->el[i]);
  }
#endif

  fprintf( file, "}\n");

  fprintf( file, "}};\n\n");
}

void
field_tables_file( FILE * file ) {
  uchar buf[32];

  fd_f25519_t fd_f25519_zero[1];
  fd_f25519_t fd_f25519_one[1];
  fd_f25519_t fd_f25519_minus_one[1];
  fd_f25519_t fd_f25519_two[1];
  fd_f25519_t fd_f25519_k[1];
  fd_f25519_t fd_f25519_minus_k[1];
  fd_f25519_t fd_f25519_d[1];
  fd_f25519_t fd_f25519_sqrtm1[1];
  fd_f25519_t fd_f25519_invsqrt_a_minus_d[1];
  fd_f25519_t fd_f25519_one_minus_d_sq[1];
  fd_f25519_t fd_f25519_d_minus_one_sq[1];
  fd_f25519_t fd_f25519_sqrt_ad_minus_one[1];

  fd_hex_decode( buf, "0000000000000000000000000000000000000000000000000000000000000000", 32 );
  fd_f25519_frombytes( fd_f25519_zero, buf );
  fd_hex_decode( buf, "0100000000000000000000000000000000000000000000000000000000000000", 32 );
  fd_f25519_frombytes( fd_f25519_one, buf );
  fd_hex_decode( buf, "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", 32 );
  fd_f25519_frombytes( fd_f25519_minus_one, buf );
  fd_hex_decode( buf, "0200000000000000000000000000000000000000000000000000000000000000", 32 );
  fd_f25519_frombytes( fd_f25519_two, buf );

  fd_hex_decode( buf, "59f1b226949bd6eb56b183829a14e00030d1f3eef2808e19e7fcdf56dcd90624", 32 );
  fd_f25519_frombytes( fd_f25519_k, buf );
  fd_f25519_neg( fd_f25519_minus_k, fd_f25519_k );

  fd_hex_decode( buf, "a3785913ca4deb75abd841414d0a700098e879777940c78c73fe6f2bee6c0352", 32 );
  fd_f25519_frombytes( fd_f25519_d, buf );

  fd_hex_decode( buf, "b0a00e4a271beec478e42fad0618432fa7d7fb3d99004d2b0bdfc14f8024832b", 32 );
  fd_f25519_frombytes( fd_f25519_sqrtm1, buf );

  fd_hex_decode( buf, "ea405d80aafdc899be72415a17162f9d40d801fe917bc216a2fcafcf05896c78", 32 );
  fd_f25519_frombytes( fd_f25519_invsqrt_a_minus_d, buf );

  fd_hex_decode( buf, "76c15f94c1097ce20f355ecd38a1812ce4df70beddab9499d7e0b3b2a8729002", 32 );
  fd_f25519_frombytes( fd_f25519_one_minus_d_sq, buf );

  fd_hex_decode( buf, "204ded44aa5aad3199191eb02c4a9ed2eb4e9b522fd3dc4c41226cf67ab36859", 32 );
  fd_f25519_frombytes( fd_f25519_d_minus_one_sq, buf );

  fd_hex_decode( buf, "1b2e7b49a0f6977ebd54781b0c8e9daffdd1f531c9fc3c0fac48832bbf316937", 32 );
  fd_f25519_frombytes( fd_f25519_sqrt_ad_minus_one, buf );

  char const * header[] = {
    "/* Do NOT modify. This file is auto generated by fd_curve25519_tables. */",
    "",
    "#ifndef HEADER_fd_src_ballet_ed25519_fd_f25519_h",
    "#error \"Do not include this directly; use fd_f25519.h\"",
    "#endif",
    "",
  };
  for( ulong i=0; i<sizeof(header) / sizeof(char*); i++ ) {
    fprintf( file, "%s\n", header[i]);
  }

  field_constant( file, "fd_f25519_zero", fd_f25519_zero );
  field_constant( file, "fd_f25519_one", fd_f25519_one );
  field_constant( file, "fd_f25519_minus_one", fd_f25519_minus_one );
  field_constant( file, "fd_f25519_two", fd_f25519_two );
  field_constant( file, "fd_f25519_k", fd_f25519_k );
  field_constant( file, "fd_f25519_minus_k", fd_f25519_minus_k );
  field_constant( file, "fd_f25519_d", fd_f25519_d );
  field_constant( file, "fd_f25519_sqrtm1", fd_f25519_sqrtm1 );
  field_constant( file, "fd_f25519_invsqrt_a_minus_d", fd_f25519_invsqrt_a_minus_d );
  field_constant( file, "fd_f25519_one_minus_d_sq", fd_f25519_one_minus_d_sq );
  field_constant( file, "fd_f25519_d_minus_one_sq", fd_f25519_d_minus_one_sq );
  field_constant( file, "fd_f25519_sqrt_ad_minus_one", fd_f25519_sqrt_ad_minus_one );
}

void
point_const( FILE * file, fd_ed25519_point_t const * value ) {
#if FD_HAS_AVX512
      fprintf( file, "    { ");
      for( int i=0; i<8; i++ ) {
        fprintf( file, "0x%016lx, ", value->P03[i]);
      }
      fprintf( file, "},\n");
      fprintf( file, "    { ");
      for( int i=0; i<8; i++ ) {
        fprintf( file, "0x%016lx, ", value->P14[i]);
      }
      fprintf( file, "},\n");
      fprintf( file, "    { ");
      for( int i=0; i<8; i++ ) {
        fprintf( file, "0x%016lx, ", value->P25[i]);
      }
      fprintf( file, "},\n");
#else
      fprintf( file, "    {{{ ");
      for( int i=0; i<5; i++ ) {
        fprintf( file, "0x%016lx, ", value->X->el[i]);
      }
      fprintf( file, "}}},\n");
      fprintf( file, "    {{{ ");
      for( int i=0; i<5; i++ ) {
        fprintf( file, "0x%016lx, ", value->Y->el[i]);
      }
      fprintf( file, "}}},\n");
      fprintf( file, "    {{{ ");
      for( int i=0; i<5; i++ ) {
        fprintf( file, "0x%016lx, ", value->T->el[i]);
      }
      fprintf( file, "}}},\n");
      fprintf( file, "    {{{ ");
      for( int i=0; i<5; i++ ) {
        fprintf( file, "0x%016lx, ", value->Z->el[i]);
      }
      fprintf( file, "}}},\n");
#endif
}

void
points_matrix( FILE * file, char const * name, fd_ed25519_point_t values[32][8], int n, int m ) {
  uchar buf[32];
  char hex[65]; hex[64] = 0;

  fprintf( file, "static const fd_ed25519_point_t %s[%d][%d] = {\n", name, n, m);

  for( int j=0; j<n; j++ ) {
    fprintf( file, "  { // %d\n", j);
    for( int k=0; k<m; k++ ) {
      fd_ed25519_point_t const * value = &values[j][k];

      fd_hex_encode( hex, fd_ed25519_point_tobytes( buf, value ), 32 );
      fprintf( file, "  // compressed: 0x%s\n", hex);
      fprintf( file, "  {\n");

      point_const( file, value );

      fprintf( file, "  },\n");

    } // k
    fprintf( file, "  },\n");
  } // j

  fprintf( file, "};\n\n");
}

void
points_array( FILE * file, char const * name, fd_ed25519_point_t * values, int n ) {
  uchar buf[32];
  char hex[65]; hex[64] = 0;

  fprintf( file, "static const fd_ed25519_point_t %s[%d] = {\n", name, n);

  for( int j=0; j<n; j++ ) {
    fd_ed25519_point_t * value = &values[j];

    fd_hex_encode( hex, fd_ed25519_point_tobytes( buf, value ), 32 );
    fprintf( file, "  // compressed: 0x%s\n", hex);
    fprintf( file, "  {\n");

    point_const( file, value );

    fprintf( file, "  },\n");

  } // j

  fprintf( file, "};\n\n");
}

void
point_tables_file( FILE * file ) {
  uchar x[32], y[32];

  fd_ed25519_point_t fd_ed25519_base_point[1];
  fd_ed25519_point_t fd_ed25519_base_point_wnaf_table[128];
  fd_ed25519_point_t fd_ed25519_base_point_const_time_table[32][8];

  fd_hex_decode( x, "1ad5258f602d56c9b2a7259560c72c695cdcd6fd31e2a4c0fe536ecdd3366921", 32 );
  fd_hex_decode( y, "5866666666666666666666666666666666666666666666666666666666666666", 32 );
  fd_curve25519_affine_frombytes( fd_ed25519_base_point, x, y );
  // fd_f25519_tobytes( x, fd_ed25519_base_point->X );
  // fd_f25519_tobytes( y, fd_ed25519_base_point->Y );
  // FD_LOG_HEXDUMP_WARNING(( "x", x, 32 ));
  // FD_LOG_HEXDUMP_WARNING(( "y", y, 32 ));

  /* low order points */
  fd_f25519_t fd_ed25519_order8_point_y0[1];
  fd_f25519_t fd_ed25519_order8_point_y1[1];

  fd_hex_decode( y, "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05", 32 );
  fd_f25519_frombytes( fd_ed25519_order8_point_y0, y );
  fd_hex_decode( y, "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a", 32 );
  fd_f25519_frombytes( fd_ed25519_order8_point_y1, y );

  /* w-naf table */
  fd_ed25519_point_t base_point_2x[1];
  fd_curve25519_affine_add( base_point_2x, fd_ed25519_base_point, fd_ed25519_base_point );
  fd_ed25519_point_set( &fd_ed25519_base_point_wnaf_table[0], fd_ed25519_base_point );
  for( int i=1; i<128; i++ ) {
    fd_curve25519_affine_add( &fd_ed25519_base_point_wnaf_table[i], base_point_2x, &fd_ed25519_base_point_wnaf_table[i-1] );
  }
  for( int i=0; i<128; i++ ) {
    /* pre-compute kT */
    fd_curve25519_into_precomputed( &fd_ed25519_base_point_wnaf_table[i] );
  }

  /* const time table */
  fd_ed25519_point_set( &fd_ed25519_base_point_const_time_table[0][0], fd_ed25519_base_point );
  for( int j=1; j<32; j++ ) {
    fd_curve25519_affine_dbln( &fd_ed25519_base_point_const_time_table[j][0], &fd_ed25519_base_point_const_time_table[j-1][0], 8 );
  }

  fd_ed25519_point_t cur_base[1];
  for( int j=0; j<32; j++ ) {
    fd_ed25519_point_set( cur_base, &fd_ed25519_base_point_const_time_table[j][0] );
    for( int i=1; i<8; i++ ) {
      fd_curve25519_affine_add( &fd_ed25519_base_point_const_time_table[j][i], cur_base, &fd_ed25519_base_point_const_time_table[j][i-1] );
    }

    for( int i=0; i<8; i++ ) {
      /* pre-compute kT */
      fd_curve25519_into_precomputed( &fd_ed25519_base_point_const_time_table[j][i] );
    }
  }

  char const * header[] = {
    "/* Do NOT modify. This file is auto generated by fd_curve25519_tables. */",
    "",
    "#ifndef HEADER_fd_src_ballet_ed25519_fd_curve25519_h",
    "#error \"Do not include this directly; use fd_curve25519.h\"",
    "#endif",
    "",
  };
  for( ulong i=0; i<sizeof(header) / sizeof(char*); i++ ) {
    fprintf( file, "%s\n", header[i]);
  }

  fprintf( file, "/* Ed25519 base point. */\n");
  points_array( file, "fd_ed25519_base_point", fd_ed25519_base_point, 1 );

  fprintf( file, "/* Low-order points y coordinates. */\n");
  field_constant( file, "fd_ed25519_order8_point_y0", fd_ed25519_order8_point_y0 );
  field_constant( file, "fd_ed25519_order8_point_y1", fd_ed25519_order8_point_y1 );

  fprintf( file, "/* Ed25519 base point w-NAF table for fast scalar multiplication.\n"
         "   Table size 128 points, i.e. max w=8.\n"
         "   Used by fd_ed25519_verify and similar. */\n");
  points_array( file, "fd_ed25519_base_point_wnaf_table", fd_ed25519_base_point_wnaf_table, 128 );

  fprintf( file, "/* Ed25519 base point w-NAF table for fast const-time scalar multiplication.\n"
         "   Table size 8x32 points, i.e. max w=4.\n"
         "   Used by fd_ed25519_sign and similar. */\n");
  points_matrix( file, "fd_ed25519_base_point_const_time_table", fd_ed25519_base_point_const_time_table, 32, 8 );
}

void
ristretto_points_array( FILE * file, char const * name, fd_ristretto255_point_t const * values, int n ) {
  uchar buf[32];
  char hex[65]; hex[64] = 0;

  fprintf( file, "static const fd_ristretto255_point_t %s[%d] = {\n", name, n);

  for( int j=0; j<n; j++ ) {
    fd_ristretto255_point_t const * value = &values[j];

    fd_hex_encode( hex, fd_ristretto255_point_tobytes( buf, value ), 32 );
    fprintf( file, "  // compressed: 0x%s\n", hex);
    fprintf( file, "  {\n");

    point_const( file, value );

    fprintf( file, "  },\n");

  } // j

  fprintf( file, "};\n\n");
}

void
rangeproofs_tables_file( FILE * file ) {
  // uchar x[32], y[32];
  uchar buf[32];

  fd_ed25519_point_t const * fd_rangeproofs_basepoint_G = fd_ed25519_base_point;
  fd_ed25519_point_t fd_rangeproofs_basepoint_H[1];
  fd_ed25519_point_t fd_rangeproofs_generators_G[256];
  fd_ed25519_point_t fd_rangeproofs_generators_H[256];

  fd_hex_decode( buf, "8c9240b456a9e6dc65c377a1048d745f94a08cdb7f44cbcd7b46f34048871134", 32 );
  fd_ristretto255_point_frombytes( fd_rangeproofs_basepoint_H, buf );

  char const * fd_rangeproofs_generators_G_compressed[] = {
    "e4d549716460013e71c032240c93ea1b1969cbc9e89c5d6b43adbf6c1df10724",
    "d6728b558a7b439c64bc077828560391e30b589314a999648d5f8cb471725f04",
    "76c764f6854b782e38c65391d9cbdc5b6393b951ec450ddf75d05aab183e855c",
    "ee2b3649b4a4b5e3a7c0cb8abd1efd953e4b568a9beec95fcd52c67ff4cc6d2e",
    "3ecd9d5e21619fa3f6635a3313dbaa7c659936f7f4f1bffb851c69cce050814e",
    "6ab5462e04402818e844d97269bd93756ad748240f61ec27762a21f832e9e139",
    "7095d49d127a723ae98dc2a6abb14a37581a3dcfea3b726e76920d17b88f5531",
    "ca7561b6545ed5d4c0ca72458447da616fba1e714d0256e0fc0859a293f3133d",
    "dceb835fa7ee9d4024d12bd2c0bc01c8be45c876d7cf5b57539c76e15236e728",
    "94d323f017a27bbe4f2f9804363641092810a3c6efabe419e1f40b7215ecea62",
    "382a85f9f38a7702fd1d92dd167df5a5a110496fd5954ab2eb92937fc1be332f",
    "ea88d22f1d5f6ba7495560f294d48d4d4379fcb871a6c5f7a15c9c47aec96031",
    "688e1087319ff808d04732f21f1242f9b34e16ae94438c2c597f9cf007e6b476",
    "643bf60606ff1eeb93a69288c4ec3c78e0c67224d14d51323bbca31b4ba84136",
    "8e6b667985b67b75301dad494e382e45afd8b6a3abdc1ea26d601a4c2b1b1372",
    "ccbb95129da57af63035bdd750595f5e1ee5f8692c3fabfd36fa5b07a8a57440",
    "081f63c0c7ccbf8dc992580f45b95e9d737dae032dfaf0fd841771722204bf0a",
    "908071c81fb50b3adacf49188eb59ff66e020f6bc20d00b8fe9343cef6054136",
    "c2c2b75b52e38eda4d6118ff08261b2e089366189a6c2e6cd5c3ae09352ef570",
    "8c901c26559dda9aff73f36481515a52d18a3c2f0d405a24e23fd7115b95db1c",
    "1835951cd3c5d80ae54d607049de020fecc543f781f949af2ed20e51f4d45e03",
    "5863f5130171d84cb8c063ac97f0cf676bd265b3fafb47f29f6ff4882fc16b49",
    "2ead9fd103f71c6f20e4fa4da100940feeee73e0a66b3bcfcefdf50842e8630e",
    "380221b28fdd76cc84765205182e7701d48f0858ebcaa627fcfcfaf20582843d",
    "8c3b08f97fbae882f4262a7c58e21495ef8465d8b2d30947cae54707a0e45010",
    "983d12247d166c580f0041fa92f0363357437b8dc2e0334b20d2f7a830968815",
    "d0e3a379cf45e3622a4e356837fbfd56cfe1fd742592c543160ebe759d62ed1e",
    "34f09d4405961d1a8976f48cecc5caaf3b7a0c2adeb0180d4872e05671f2ce1c",
    "0a5b10a45b32631b6c5ad460d86c17c6802b0a39388f0ff93ff74b7f5b10167b",
    "301019a0c76909a8b303ef88b4c338df89458ed81af37dfc2cf066a81c625777",
    "6e94475ffd0b34b8978a0b77cf3322c54491bb88d177efdb51be96db373e176d",
    "9c3077463ce9dfd62aa315110f2e44b7a67afaec3f2e3b537a5d1b98fb59136b",
    "b2e8654473ed12ccf64471d8bc262d4547cc76e14c0f7a295e96365bf941665d",
    "7058592053fe73a554756caa0c608fcdd02352afc2acd94814b3e1fe066a751a",
    "426b348416fa85577a34853ac4db5096d125c86b7d34866d69cb1d5c39bc2879",
    "82d913b2902316a81a55885342ec34c541ff22a91e70f8ea5f291798e206d43e",
    "deb73492fe1539390a9c716ca0d077018894f08ea6257e49a42730ba7489c509",
    "56ea786299dd225849625f24f0d6818adcc2c89c9fcd2b4c1de28adb3f8c3868",
    "6c46725943d1a00c8bb7c3bc21a34c8683b4c05b978b861defc125e6cb18997d",
    "9a655724ec2efc2d3b94d7d51e010070732dd1bd7382c2bede8be394c98bce10",
    "1e928acf03338006dac0af65e49847f9ee7d9aa62437f11152a1dc2f7f2ad35e",
    "46cf03a1b93ae908e27a6ecbc11cd91b49be7d96b3d9e0ff62bb4f85e46cc92f",
    "bccacbcf5c7a60363e8e3b1a05848f74bf26723ecf8071814ece47880b077736",
    "0ab3773459f79e25b602ade0b2fd947eadca705e9e9b199881a2775230baae14",
    "e2945960f3ad6d0b519474a300ccc48b6185ce0753cd9bafd2cf4bbb74713431",
    "aaa3ffa0e5af5aed6137663f5e83d29af729b8644a0de8815f3df0dd44538c7f",
    "c6316e0febd900c84f2cb95902023fb80364e8f90ac7e101cafd418c1d22bc57",
    "4cdd7651450128d5a2821d173c0b6eab06b7755372808c6d84aa8c5aabb8ff76",
    "ea8db734ed908533cfeffabeb9b84f24b858502dc6d7f7c9be2038902cc25109",
    "16948eab85b0892f3667da404637f28275aac2b49524b4bc8df75d6982b73328",
    "4ca94c807fe45e64d817f48e36303f350d09672840a6fc9de1d3b685e3408c2d",
    "5025282be0f1f81c307f4597bf4914d1b84b1561619fef6a7d2720e5a5346f2c",
    "c61a731e2d439cd8786c94a0aa373ae2f2a61c51fb9b95f7577aa2da91fdc61f",
    "a2aa48d649350bcd3af0296e1448d425c9e317f731db32476727086b4e89bb69",
    "98b56d626ea75eb4872ad6a766c99ebc1810e08baed737b42f0dfaeb1f8ef442",
    "ca3a0b77e5eec4bb218f7b7938def2205560e072b8c08b2237096b086488dc53",
    "fa8c98aa83c2a3a525c455fc786d229a9d25eaa7f2298656649891882c031518",
    "6831b0cffa6192e9fff7dd291bc79e7d7ed62c05f2b22048b43d9c83e25c821b",
    "049314044403967b2a48e9d31ebe05b4dff3d6879e82f11a488acb5b4b166633",
    "c0fb8f9662c9b47a9eda33a9a1ac27a874b4faad5cddf7acb03eec2e2166d876",
    "92679548dc18a256d5d78e76dea6a50c34370ff2a448acc4156a3ac49fe91447",
    "0aad87d33a3c13c2913520748d89d8701b77efe9d67418e23ca3ea16ea51a621",
    "e205cf463776e31fb5a61b3e6f5278e850189c97aa05966f19044b353fae0e7e",
    "0414d80103ade257f12dfb87d5a9cbfb80f2c6383aff487d86714fbcc73e006f",
    "7af1c88ba7699f969e45f568569bf343a94b15f3b26b5b33c68a77141a46533e",
    "f8264a0e955e5165f346ebf178c07058d7f44966c07a1135038d589f5964dc0f",
    "0a005580e1c0cf0862363e6d3921e2097ad8a0da801e813801c4f569e548440f",
    "669c056103001d60a9cf184862d9bbcfd00e7db3e4e59a4ce637ae2f8e67a872",
    "64ece176de130db9cfb451ad92faf524411f13a282059e28b774624f7d6fa545",
    "ae5ec3ab2b22aada624ce8cf80f4cb8dce2fb3c84b774e6a8edc92d992a3c81a",
    "54d3120385b105d684b1fa387f439cbf95a18981d6746016902c5df86164753e",
    "64e54f3fe3518e539134263ca787cb27405bc3419b0baac9e372c343de176b75",
    "76f44b4d8c9b960b78523501fc83f88d8143630d7935cf24b877bbde71089575",
    "7e2961d405251b9dc4c4cba3b7aa357e009fd03c34eefaaab155185ff5ac001b",
    "50d82950690e9387176f23b1d8ddae96df7dfd83951d04f603df29a884d7e67c",
    "a48b050799457737eab0d072332f97b7b1c95f65fd461ddc2d1d0ea9ad528d76",
    "d09fdd8553d1465f9a2aa0a72156a886d2f3f8c22cbd27a379073a2b3c200330",
    "a847a1afc9f7995340b6a1f6e834b05e49523c7b8169e60f2ce85b7608b49010",
    "2ec506db460150351762a35fde30a8c545bab54ab3556885fdff84588e288326",
    "2086af6aadfba71e2e436eeed353c362f933f75928d4fda8b2a0788ea1070564",
    "8a9e3cf54afad7eddc4b2f6d162260df83129d3fbb445c0f83471d073c7a7707",
    "86ffed3e3e34ae81dafc7d7f073b4c973b237b889202afd7ef3d44e936c6eb38",
    "b4506433c0654dc8d14867d1fb76b35f46f7ab5ed7b561a4a09bdd7398232832",
    "3864a770d1fff4d89a9ef4e94189e52076146717aa90f1658ff4794a6f6fd219",
    "3e089de78fe0c15fdc37bdaece4d85996ea1cac06acc61533a0592b673eb8276",
    "64728c64848b70c36618799f3c78404c303cc4fe655cd9a4f0346d726315a566",
    "3417da8ba070164605ca018ef800b873e216002772d317602f3072feed703c05",
    "b6691c6871774e6057e91e98c20bb90991db66303375906a77676c9d41b5fd7d",
    "d27ba9904d226fc8f4c3e78f3555bfc865de160f5ddf20023d4e0a5bc6d2c522",
    "dec2058476ad54e3ac22dbfa1de7a55ca5b0153e4679a2af3f0af245bf79b025",
    "b82674aefae6a580e97055a74493e62744ae3c5e78109f30d5a76bb216070058",
    "76362173c372165b1065a6420aea965618171596c05153e4c7f3e29e8247220d",
    "a6f9711458f3ae41aa179d3d5c420b64a340b760ea4c9fd23d57315cc8bbd20b",
    "8c1560a1a29d36ff46500c07ed2f9911a09e4f9abc8ff491f313bdc400855b7d",
    "bac980cef11dc13aadeff4abf8e699bf24dc18e25f88e7382b593ccb649c5e0a",
    "0c4c78be0ab524d181d523c522d0e39ed4f8b45286d96ff2c881c698222d1b7c",
    "6e6d22dfa3a095bbdc610b049e513540f4faeb4b22ebcc70cfa0139232b7c83b",
    "362ad41cdffd0535d5e0e4407d8d21b748154a56d22acb61fe15c0b737386646",
    "d874eee12be8d65e8e670a11e2ddd040df4b8a4a095c25e0a90373284d9a6f3e",
    "baed5db8ee28e919b2ba2a5309c84ad241895612ff5d9980cefb551b15c48d75",
    "a2c2becc40663d4c6242f487ff3ee796049be623942fbce85a520b10799abe10",
    "ca4afb446754c98cfd5e1794ab23de283b01c9063d1fd03e7c89408514c9cb2d",
    "2acd013dfd487ecf9e5ad7633671dd36898dfed021acf4cf6200ba192419952b",
    "faeb57a1ad617df5d3bfc32fe86b4e767dac20766b96163c85707121632f9a78",
    "529ba7f5b66930bfb2073d8c0ab0be9ef48b0d9a75bdd6eaaf31f9117d7bf456",
    "087369af321aeceb88adbc9764b3937ec8de7bcf888df7e84ca2ba00666dbb22",
    "d6a3d1fdedf554cfd81dac3989c11c92c56ce515255aaabbab3f9097a7541f68",
    "00d3c7b5b33b24335cf33c5af1bbe467bb581c03456841269ed8512582dda84a",
    "a876a59b96002b530332b625737fef6aca2cd7c64e72afc57e3505045b357824",
    "a894bf286fa90e11c9a56e2370d3d1b7d09d70dbacf2cd04a69d700d676c043e",
    "a69eb32eb3ad0e84d0b439d8620367ed5246b6844eedb15a1dfaca3cca534613",
    "8cef6db0a63768ecb0c9f96fc51a6ce38f031f2943e2959e1687171beafcda36",
    "2ed6a88ff9294b6a36e605324b871c62615e4d53f4fefc2a39fdd910267b1e6a",
    "4416420c780369147c445cd4ea33cec3cdc37ac839c67c868c7ebbf9902dbf4e",
    "2a1f15451347bd263ea281c4897956bbb33d0b15e35a70a8bed552638d86096c",
    "fced63f1bf0500fd81d59758cc1f0e1fdcb39a8a7af042e398aa243d158b9c3f",
    "9068f079b2f60b15ab2afcc3d17eeb238ee0884c1cb71673163535a30c1d5d7a",
    "2ad3cb6a7b0af5fdec56365060e7f32252bb300282d2475b63668837293eb43f",
    "5c612f2222eb05ccda318b2eac9dae1043a533e80cb31b277e53af68cd76b97a",
    "2e5b46f0a000f6a21d9f2e5267225931aa91f4132c90ca38526280686b457a2e",
    "b806e0d4e4a3282ba587d588ced6fb800297b946e8b92a26e146de6fa93be510",
    "8e20c3a7f8547c1d23349af1ede67e43d62b461f3040855d483e4e600363d571",
    "6c0222e70a1b7a5a73a7420949a307149b3b6c918cc37c7bf405a5e0ea212e4d",
    "7cc1bb5e47491f3fa53a1a10782594f6ff2d7505369da394e16675cce17f5068",
    "028bc2746bfd20089ecf4957a4c06410f8965ae70efa0b41b09d8b1b1e7ec376",
    "d6df6a9ba1535f07c6c91a63f1072b408f91f96edc3141d8808b5c0c67b73f2c",
    "2a3039e66e5564cbfc467efb529bcf73e0b1d2d83a2bafc93bb88ea82282ed4a",
    "74f0ed10afa1298ef5eeeb568aecbbf45d26fe900456882d6e62cc247fa71744",
    "0e0be53fbfb782a69419dda05d4357d1f955fef0a6c3e855a3c2e5c99bb2577d",
    "a697d567401d4a8bd81d8fd76ca9bab039acd51880a97e0bac8deeb7497c303f",
    "30f0fb87e340b36be3a1511522c269a6f546eb010e6d7150641ac2643ac68f67",
    "9ccddc9d64bc5e79db25fcc5ca981b254ce90f6ced5f8e5d51b5766a9e55392f",
    "8acc43649ab80d52bd9db0a761c6bbf5ab1713e5112efe938342abedbcc7e31d",
    "3a462fa5024649bd3f526ba748fa817b6e2fabac25c41514f5def67d0905ee7f",
    "66a9c23108d55967ddfc6e48698d4d73d52d7e9ebdc049e8fa14a0c7a83a2b28",
    "9a50d30136f1b41413b0c606d5509ece69137dce3ad1fa2f7d746316546d4510",
    "c8d2dc25c40d1464c9ba1540f3312500feb19ecba62a20ee8d13202fa074897e",
    "3c9a2f79c72d52f158840d524cb93733317a168d3e33d9ab88c7293d77a52a76",
    "ee0d427c18fb5726ddd6d9bd7e82ddce0752071e76e30c1f8ad9622591ffcd60",
    "76d0c35507aac3417abe975cdc24d0c39e65fc1f6e7cf09cff6a346ad6932164",
    "ea49a21cf249714293b40ddd899541d63c699ecc1cb74f4bfb6c761d0749056a",
    "dc4ba57887d30866a709f278ce1da12d8ec09579f6d7b1eb249c2fa3baaea81d",
    "2ef188ee3766a55e195b94ceba5f40a22944457d7d5536e6f05301239c186f3e",
    "569744725f693484c165a7eeacaba672ae27ba19efa95ad60108129c5a0a8b7e",
    "c02b83a714e25f662660a4ab48e8bf422e41cfe2337dd447ae37fdf836387b13",
    "7043a03a98da05bfd6433091ba534e776a02fa2ac0fcfff884ed8c5db66eca64",
    "7a52401bed9b23e837012fbd58741fceac102208668fee6f92b7d5becf83e720",
    "a656ab769f7116e2e3b03643d6c90392e1203fe0bb3d5e14dbc1899c462bbb1c",
    "42ecf97c86bcc2a63630ebd3432e6dd37ef42659e6165fd60e8fd51f419f662d",
    "4cb3df27ed1a7f8f22806edef8f8a2d14d852604d1e4843db39dee23ef38c621",
    "9c9e87991325222bcb37ca501b404d1712e22c51eaa00474763b30c53aac7249",
    "3c6ab4f1fdd5839c235bb890ccaa87bcb5b2567eb22205c61b43b7f38d117723",
    "8066f28f9e89e66595442eb7a83728ebe16cb2e1215d231870cb428de2161849",
    "28ab713994c470c7d372a734d2df4be8d69b3f07f48ca5e1dfc0d5949edd1779",
    "2cbc2fcf333d4b415151dcf6ac59b75fa8e8b1b5235a07c64b1addbd1b6d5b06",
    "244054d258deeac96e418bbf8c76385f43361904efeaa6f0c5920fec257b032b",
    "d6ea061006c88b7a8070ad52dfe6b03b1d585aa350ba9eea3383748cb2ce4513",
    "e0f7dcd62e4a89517ad24c71a1c8fae014ea8ac8ddf8cc560e1602bb4506dc6f",
    "a28b9d66bcdd59c6d8790abadc5217155f6b1d18e129f4b51d5724e9b6b8740d",
    "385eb3b3bec533d6c8bf32e237da1f4f250f94367053f9defec586743dd4bb1f",
    "cc5ba0263d213c318d772c881e03bfd68146a208a0685145cebdacc01622403c",
    "3857aa5f542ce94b8b34258a565c60a1abf538c121b76b8566129319b8dbd756",
    "bc6f62a7bcea2f21e2906ce44a64633a9ee365d47d94f21d7144647538978933",
    "5896423fd5c551f1d3776eaf2ca11b32747693aa79ac2ea51672d4733ee33f7f",
    "d4ec40c158e78cd1977abe1b44fb198e108406059ad7d3c9f865e20d3550352d",
    "f8def25911497684a99dcec941af645545d03ad636f11b4966da0871fb12e06b",
    "02a573fb4f2bede16d1a4a30b7e5ce5a3957fae155dce1ebfec40f7f4f46e12c",
    "305a230a00a37259270f3dc67e47e80abbc41c82c02445c7c78c488dd2bcdf32",
    "2a151965db671a6a7f0c18c52148e78299d56bb10390cd1ad6dffe0acf80f469",
    "2e19afb1da7976296448f2946060e6cc045ffb89aad310af02a1e985f1d85421",
    "68fd9dc15dd2a2b0be48550c2d869fc7939fd459a707ad36e3b2f30bd1ddd24f",
    "0ad257e42e6c4f0b50531edb7bc5a79faa34bbdc5938d4c84dab994fe741a92d",
    "e21bc99405b900d8be96fb316c44724ef1f668889717c4be112ce9f6977d350b",
    "9850b9b1a5a99aa8c8f1c06732376b5c962c4ebb9cd0793343dd61aef22daf73",
    "3e06a57f6406006e722f9f2f2cd91e17e5b7fa12e80196322da316044370a230",
    "08573e3b19f92e8f0e3f4cb61d90a872da57ee42f03c33f41f39a158e851df68",
    "521041c95538fb81fb2cd0419138dc2a8d19ba366836bbfa767cddeb1ce93276",
    "0233e8e2e8c8dd67f20394a80764568df1ae1c48e1040e74dc45061c0f74d01a",
    "f8549ebd84c638a871ceb1337db1d8d107066278226da32c0fc7b38286ba0d47",
    "5c4a2b7508595fad7b4d7cba4c5b12aa5d6a0715979598edbe50dd7f4150a279",
    "7e25850789d66a2dfde8b056d09c73e96adb059575493c4c3e7626436377a369",
    "aef4dafac5dcc365cd06e76463539836880ad2baf25b6b49544552e9cc08e510",
    "d0e40c823113915b9520a0c2cd5701dcc678283f19f81f17d2c462dfbff0f325",
    "f2966ceecfc4a5b93b596b7bb863ade3a7f30c92eba229baaec407e98866b322",
    "2ec132d555e9696edbdc00d90dbe4987d58e47315b955a12751e254a19a1b94c",
    "60de5f76945d5c9fd5ebca3ae17392084f61300f62ca534f2e8d0e5716f29c1a",
    "f201c923c680e0043c5b0f56b0a8e1092636924ae4740a5ed8346dbd697c9f0c",
    "5e8df68bc333fbd2bd34668c73ec07459c7fffccbb7ad5ae1e730d662ef3c022",
    "f6ee9f05b2459622d0bf948b969357fecb0089b548959b5cdb360c570901ac1a",
    "1836e0de806f4e88949378a4e4af2a2684d87ccc8f05cb481d98b80cff35a84d",
    "8431be8d9f9b4af991764803c89d4829ffe3852c8e6ab1bf1c10ae80f0fc6c68",
    "c82334ef7bd1d5e43cc4dbf793f34373db665d01c6bdc9dfcb30a5084cd1b70f",
    "7a45d8533418567b38da5c26a0b1e13d6c4f17298d9e2e787cbe612fb807746b",
    "120a8e2d889f036cf4771bc7bb054de27616869494f3f6d22395c7e34b546b06",
    "b8dcef394ea2979a312f9bc57b17288a85024c82418b3fc94481eb84f9e01908",
    "a6669551d58692cd4f04c6a9e541b754bda542b7a0dc564a5b8d4ac6dc83124f",
    "40fd88ceccca3b963e5e809f68562f672fe8381c2d12fdb5f3946e2ecba9771a",
    "144c4e7c166619b6955a96da8b190ffdac3b798bdeb7cd7aa84a509ef56ff47f",
    "d81c1389cb06e93e08e593773e1bce8b3c024ad84708419032c72c8088b85e39",
    "7818803a40fd67e077c6587632a199a093cfe0a970c8ad83c886e599b38d993b",
    "9a3e6f2163b97dbc2be0bfe4f460c6997286716af28a6943c652984aa4201066",
    "00b07dad6051e2fd2123e6fa70ccd08bc5bb6eda3a2747dea0ec592b22020178",
    "6c719944be2da4d4ce7e0f922da4b3dd66a9664af4403c9c2c0abd8532180a6e",
    "f6ef27d48337852b1d2953e139c6ea65ca9e47e8eee616d5fe423a069389893b",
    "bcd4d3055bd4f2e902f571d5e7c39e06eda2525d0ff2076d5fb5ad5feb9a1767",
    "d69fd1fa1f1ac6eb5b7224c8596317ee0faa3cbd816e2c869fb795aed6b85423",
    "784c7dc268ea2f98ba38767873b589ab4225830877e52329a62b17844c15ca77",
    "868b2a6d7a418ac84dc92029d513779a5802a514f45afc03470fd7b410c8f74b",
    "04945476b953aa2d7034cf07501e9199f01e8b781ac12cd6cce033a378389a3d",
    "5c380bd3be1ee3bfe78852492c37d8ba7c963174c5ae893d5f0f639d33a32a14",
    "1ee772a179ef1a9837de2df704ab7378a750c1d268224c1bfba0e98b4aff2934",
    "78d76eb2d3d14c39007569117054e275c23879e74ecc7c61db2e56bf45191665",
    "24b0ccae650ffed9d90bc06fc53faed437d2c8e92e578cf83e1f1494ae738b0f",
    "e6be1e189b8d6d0931e3e6e06def277719215937b03b8d90b53ecd9cf26f5108",
    "ca312b00de0515459be163a8f5758970fadd58e9813653012da949b3a3f66567",
    "e69656caa30ffd5101e944eccfd18c2bdfb735af3c6c5d8eb16c6d39f8506d4b",
    "70710bea4adb708993cfa9abf9703bb2946a1264f04a9caccd399d6c276bc80a",
    "8cb7b6eb96f03778ea11ace286b6d5156c2bd1f74650dc4d6ad663b15fb67332",
    "a6a4365080c55a58b9e3081bfe71294dd498f7995cb1a4d35de17e0838abf34a",
    "3c774605c2529b47557b24e53d5e7a57c500cfef2d610fe40c0dfc9c0e02c35e",
    "863c6e04f147825e26937c5d2a30dcffc8a70b359e847171ce7a1ddd357e5d56",
    "868abc357bb916f2df6519071e76640ee9e52ffc9858aaf155e79e6776efe00d",
    "66f7463b7fafe0b97cfa6391c9d8578ce559ae9a30e4bce99627a701ae0da14a",
    "ba3362b16271d6d286b9b7d30bf91615e7a2ec4de2148a04b2e9161774bff94a",
    "1c8e1c2bb2953f1d65d055781354d915313ce6c47270c2329dad5035926bee29",
    "8466bbc358b37f81103e24e67f9ae45c10561d244b5dd3ab9a3f75c38cc0a904",
    "5816d08519071abc9456fce576d02564f243a2f2df582a61a7327f856a8b3807",
    "d2cd7865e80afeb83b8ad0f46776dd03d1b9a2c715d2356c8c33297d4f0d855f",
    "505992cdb210c2939810b609a271eec065b53cc76e1bc8dac48c43194179b254",
    "3c836d48c4810c25fc1b0fc10b968a6511dced9a5610cf8e1cedb0c314c4af04",
    "b668498bd4e770cfdcb3ea1e2f3ba5d9068f03e01dbcea03dd34bda1837e0d0f",
    "aa030f2fb8cb7dfe98c7015df55f2618097040ee8b916176e854ff2f9ba92770",
    "3448a223a2625a99131e2cf99a1c9cc94719f5d850ac2e27d86c69f4de5e8578",
    "64cf2ff2d55ff194d86b15285cbe776c994b60fbaac87dcb1b1201faeb46ce7d",
    "026b845e36675bb60091850d35fd877d32cbe2ec266a10391b6f2a5c93f59b0c",
    "aee31fe0e160e94df863fb4bd7cc33d4d39714077eef7c4722ed6e0fdbc51157",
    "ec5ea6c6a5df49d83d0d3b6e46c25fc56b87fa3241fd31ffd6fb8ca81ca78620",
    "a8bf856e563016b43f7d881c5b06f10f97e0d5cee69ed2145070b77f44584334",
    "46872f333ed045df48456267d6fcde01ba8218786be1fb2dd5454f7c18f5d75c",
    "487882d2f5380d5eb70c7f8574a97b7e1828845b4f6731281b5fb0365d64a431",
    "9e03bd4d8aad556656c6e64952411a197d8d1b4339c60c0b7dc9c7023370502c",
    "fce52c4b0de564fa1631a827b992a4952d6c555cd1d32b715abd7e3794bc3931",
    "20808a6951aef9968a50bb8f252d63667a1fad81004b0c4da537282baee1f62b",
    "2c11a5e2d1a1d5d1f0764f29bced5ea565d5b30b3c76dd35315052e7e9f7b501",
    "6801d7338a0138fd8ad4e56cf541e714b597ecc14f261612d56be40a4b357046",
    "fc024376dd1fb05d17c53a6b0bac6bf7c30a812b83e01267aef5a0afe5141d07",
    "62378d9296f7cba1564561bc9b7ec6c6a1b40fadd82c7003cbfe44f225200e2f",
    "98ecb194d03d102120d69827248b8303625ce882b487dc99eaa8626746a4c16b",
    "46cf84716dd94408fcc6c8e9fc104982a5198f8fdd3a76e8e3252076bd6bfe6d",
    "8e4aa6bf5bef7c12f107aaf46393a88a66193e47eeb97f64892d147a06ec8c36",
    "5c4255fb5f5266f11187ca49fb7807e5096bcafbc6fb89e77b7cdf8e83271977",
    "ae2426608e4c8767e3dd9ea8a4e8b4df3b00a772bd3801cced0880664a694367",
    "2ef0b54a4ec3dd5313b1b77f55f1038377c0999d1815c286d9bbfaf83a0fc61b",
    "bab6487804d5703c7941b4b93b6657091b2048cc73de38c51e16a3a2e602455a",
    "60c48061ba5477cc9b58dec6beb0a1ff26d44002129d0046ce8df097a01ed446",
    "c040474b2018614f0c0346484aa4c6efc4ff357d836038632c8a31c03fc9184b",
  };
  for( int i=0; i<256; i++ ) {
    fd_hex_decode( buf, fd_rangeproofs_generators_G_compressed[i], 32 );
    fd_ristretto255_point_frombytes( &fd_rangeproofs_generators_G[i], buf );
  }

  char const * fd_rangeproofs_generators_H_compressed[] = {
    "5a85e8485fcd463d97c976bcfdbf269206e49565b3ffc872defbea4f50b61b5c",
    "427d0c0cc30af031cea0d8044846743cc34aa45e2c4a78f029371d25f4145368",
    "ba351f4df7cac755da7799e436db1d131a2803995f708697bc328b7731e08064",
    "eeb43382ef69a5e079acaae1b271f22b2ffc253c86e362fe9e1f768eab16a362",
    "98c4e87a3b4659cd80dd3cc390b86b936559b8d2aae6850377241fe740735173",
    "185a9a8f4438f9ee8bde340c1664b496fae9d276aa0773ee7c029efa2f66c06c",
    "683c58bc4927ee6c7be2d82b02ba6e1b64a88f274dfaf2363545466a7ec3db0f",
    "e096f1dbe20f142c4ab67b550689da51466aefbc56b5d20e26506eda7799f75c",
    "fad1407911e45cd3f4d8c22a708452d6c5f6e57941c1b5332a308fe8e743245b",
    "70ee5c2c1bc70f9a300a6b927f57471b9821fa6eeef4d29d5fa3621bfdd6f651",
    "be219b7b573493b795dc221a3f888b9dc178876b46e3067e9d9017a4a3a7cb5a",
    "ce99f4828714db040200222815198f171d355f9c8a3b912a170e3917ab86d15a",
    "b4701ba00d07793e337d93752f75aae0bd09d7986315ec045689fd69da206e2b",
    "16768dced97848812ebbba656ce22edf48172aa51eb7e1ff01fed4eca0675b3b",
    "c8d58659147fdc52912043e63c57823332d39a0a6baee1bd9efe740941f14906",
    "7e846235933282f6366fa1ed937f0e46a03ec3506ecca2ab2e22db1931aed778",
    "8e9b0dd1af2d40753e0aaa5edd07539f4f059b79fbe7f0c1c00dde5e23007e6a",
    "c681238050e0a89a7bbf6afcaa4287439f617a3396782ecdec2d5d7b1fc9a659",
    "40ab93c749e5cdf1edc46fed489a23ce9970f6d847bba60f7d78ea7e09125565",
    "a0f8e6c9caac519d10cf1ebf91b4251d928c6da5ba2acf65ff0bde2a3d0b9667",
    "7a2f821179b055c0017c8c544ba2b9e3d0f3a40220a2ca3ade315af02f4ea24f",
    "841660ff539c7013ee0efce33df801dfb898cda75b704ae5b08bd822d0ad8f48",
    "6c3f3fb97d557b619f9771360387b2e99b14a2f93c4a1ddeec92776ebd544c3a",
    "36ad51b7b880e732f05d954f6174065dcde77251454df280e55924b3932eaf51",
    "a04083c9002da0da8bd7a89d40bc107c7a535f63a7364965387e2e5d11a1452f",
    "ae40a434aedacc1b8d699a0d16d25ba0472898688c813dd1b94b1b5ec87fef04",
    "f401c39796fc0eb1589f998fae0ffbf7f8755fb4ec239e03fc62d073bc876850",
    "42818a9ad37ccd48f886b9e81b3a2e40099544ca9e898020ca1cedabf5fcb824",
    "5e8aa1acc4f770d497479d4a585c8ccb092de7a4ceb3f2c987bb52e904ac1e0e",
    "722840ef2344f8cd2e66ebdf8673f5a88aeb744a56213ebcb9636a15529d524f",
    "8a906bea2719564ce67afb633c38fc497cc5260143069a36b8119f8029e8094e",
    "e48fb7c4119548dc3b227109aa49bfbb6d219c9e4a501f96efc33ea4b4de8327",
    "92375ac6b887a89dea4213b21182ae96a0c0f0b078a0f6e87cb32cac3070e251",
    "40a0b4c40c0cd0720a85f5500719cfab1ce71fc289b3c3846561fe860a7c4251",
    "d80e649259ab2194182918f23e68c280c08a84a535487cafc384cc77dfa30e12",
    "36fed8e754483b296108e72c463798f79a12b7b5210fd4a4c895be97fad75b03",
    "a0e74ede38a4abcfa91b4ad9d5fbe38ce94f064b7c3d9d37bb5fe948b3f2a664",
    "5a6b118d4a1749f52e5d68233365a35ee4612ec5280f5754475c68605fdba51b",
    "b0ae38e6a2f9fd0be5946c4e2cdfa758fd6a4e76d130429cf6ab5af5b8132806",
    "2ef077d114d0f3a5d49c510ada479a7d2fe5d74c7c6eaab002706feaa0885040",
    "321ccafcf7c39a90a1de9deb7529ca005ba9de9b40f25a8442a7d065d19db530",
    "f8789cd905cb7db1d134fe9cc2fe089dbcde6afe6d40a2c1477c8fa681c04b2e",
    "90a77428779828d25b2cf200c39e975ead0c97c95b27fddcbe322375ab96797b",
    "14dd0040c4996e76fc5568aa915ba1c8a69081b3fe8a2ff6e7b5af7d2d1a753c",
    "3ceaee146aa6cdce49acb81eb7651170b6340442960ef8be852cc76b8a63e72f",
    "8ae6e203d39a34fe4116ba8229e9e22fbea24a70e84e92a88b51b1724cc1be20",
    "c8876597c1222696c732b8beb44d7ec50897dc523b4384991888058374ff6c0e",
    "743212df7f41a90210588965fd1c3f07a38f9a05d050c546165cd1ab0fa1796d",
    "e29cf67ae858975d5ca2f70987a481996262a549969a0b0b6a80b28a8885e65c",
    "e244b839850540f3c29e9323a6c11b691b899930f824cbfcaec07347c6f52008",
    "68ed44f6ea92efc4565d6b04f8e793fe2b642813e757dd90fd588ddad1ff3871",
    "88fe5a44f1829fb823c049115ac6a6927d78b301f7981271dd381927fd090702",
    "e2247be27447888a06a5c351da5fde85ac129b069e7428883c52569681647b4e",
    "1249ebbb872d75545270a62d128656a6ed2a9f5ff909fa5b2bd967f9f02ba251",
    "a67fe424b9e567d0c555c1c621e6f88a2002184ae78e646e0e76997a77c9141c",
    "5e436ff2b7b1a9b44081e0df4f1bfaff8b988c57021588c52edcf0df1521a40b",
    "ae6435c212b3845e090705db24036e247ec19646ae2e6f9667c9c2b0caf9be33",
    "44a136471686fb6f031972d1bcf6978f365b0c7adfcbc3680d864289df079e09",
    "d8c44e8ede90ceed98f5f6fa5f41681475c26f7512daa81a535e42be749c764f",
    "6c8e9b2f42ef855f39d97a08b1b1e601ff19aa4de3e0886dc87635f3d597127d",
    "eeb387f9a176c284c1f5918adc540e47a7329173973235a96e4642c2bfd4f833",
    "74d957fb6fe719dcb0806c5d12c2ccf2bf11ad6e141790797be96505683d7304",
    "981d9fc4db3b842b3a2a20309c8f2b1a76c399f111a2faf33fa7dd288951e33d",
    "8eb603fca7fd6b11289ac86bed6915445506403e7b5dcbafc1d6e086f710b03f",
    "d64bec4317c9ecd179932fdef2aac71df647152653f4488ba52475c1d5adad31",
    "8cff04ece65cfd65e7b6904f01fd7f1422ac825a4e0693008fda123541556d2e",
    "8c4261d09e19d00ca635efe48bad217f7942d2dde002b00782843822d030140a",
    "68599fdd5ae76e78cf3d427664221691822dc269b0d5b97d0222fdfa6975260a",
    "6add61876aff4a469857c9f92e14f4b620feba618d73c9a4ef094fc163c3fd64",
    "7a8bc7c856c6074b677c574b7072b19f868a409e0440f6931b7ca3690bca0034",
    "648c3a5c24ea5b21f492f821bbe813326c154eccaafce85c5b50baa6285de338",
    "b6c431772cd3173ecb4e571360593e0567bd1542d0be0a900cee7394de9a5d4f",
    "648a0e4a94ffed8d7e4a1d3983cc34bb1d27c1c38c3858b186698e5faa4a6a2c",
    "e61365b9064304129d2789d0e5bf395c17b3db93b0545c7d4a7afb9cf8967e6d",
    "06d5cf60c3c0ac36e7c74835b071b50756114d43fd4208b64211e8d364617f62",
    "78598864896264d6e13c75febfb433ea368f35698ea72ee3b9afdbb1ecbbf92c",
    "34c9c51c4cacb5dc260b1596fb8745327bf97de6ba1198b7673af97d77632d1c",
    "b43f76103bb3147d1695f12a107c583eb042b036e7f52775508e5eb1fefb1609",
    "1247417e1927e109eba7571089ee1aafca8668d2cd82b76370f1a564ef639c0d",
    "04b636290658ae780c26a4ee9d45d212b52bcb2e02d717691b1eeb51c5ed290f",
    "9601d64dc0fd70cc2162b112b8c8e63269f0679a424c164998fc8c1510d4ab36",
    "42d4d24c795814b8e07682e616da3f3797832a8d25787b747e1c7cfc8824f617",
    "a67316afb80d1dac25b2bffbb1a8d111fd2c87f821d859b34df69c08e97fb561",
    "f2a4c8ef8a656b8b4afae4e1669c7b9da510146103d69ec0e31edf50da08af58",
    "1e470a64d0d287962b01736a834e594c4e3f960ff69adfb788da888d7f572a46",
    "0433fe3558963197373da75006966d0b725938766ef1005bf881f042f8f7682a",
    "7cc59940a214a6233288f53aef09e4bf27365a965df638be1104afff2da96748",
    "60974f4f8c3712d0c6ba3c6a7d3e08838e174894cdf3c36c83921a0ec9d19244",
    "9679bc186165be6db9381520ee1538a34c28a1f3a8f600d752f016fd868b750b",
    "2af2615f68d853dd136396009273515c3cd9c0a10420ddc3e7b4a4a63cfa6779",
    "f84e5db93c2bb8ee718f889a2a0e38f3613ee497784fd32b6bea15dc515b2d3c",
    "6a9ecb99d14b7b511ce4dc6ee50cf852ae336707aaa3ef3657baa64f2285cc7c",
    "f291948c85fb170b129aa167806ae64af134a47ff20dd8226cb324c5f3f29873",
    "403b2da2352c9bc1ed9ca014f05dcad1b7e2258857d6b7381f826008c61a1902",
    "90bde43ce3ab8a5cce6529c5426569fb276cde974cf33a7cc4a32ddb1530bf03",
    "0cb32e4d8be9c31a12c6b6be4801b0f845ec71a2cf800cc84d9cb77fd775e719",
    "9857a2da1b26a40edb04355c18980404bfbfc2ca667e7d4363b52924d2389437",
    "c8d8d1a50483c7b4dd9c8a763b0a9fb5a60c0f2eb05d035e65e4b7212ccbda26",
    "4835982701b5555dcb22f8ce4db0c6087b2070e6c6bf8408378c64ea2dcdd930",
    "d2221a58b177120ed9955b45e1588f4994325812419b0392ec0efc7324ac657a",
    "d6f0be5bcdf2729aacf24eabf035c887b1305b6d5137e307b8e881a091c7c928",
    "4ecbb0df6012bb136b848ead8c4515f725d2cf03aa9cc7ade760839df8eb0868",
    "fce47a84f1d841ae8f53a1681c781eca1e9fae0fbdbf8469e71efe2547b80566",
    "cc053ff812b09d4a3c16a0ce5e6355a90776fb74a3d9fefc972b30fb65ed7d61",
    "009860a0e4d8b4f5d780fbaaf01139f3d7f5b1430c9576c5725a66b104385300",
    "86c122d4d2a22a48d58539dc70543293a4bd95b7ab892920c3aedaa2eb42b87e",
    "383eca78f0b88314e26d4f10e31796b2bfa3bd8973d352e8cb376ed2f48ab909",
    "6c3f086a09de7c747e4d23d4386678fdf3cf58d96af7b96945383388cc2c6a23",
    "80a47af583ba4990065960b7f813e6019aaf2d5a46b107a38d63a55eee67ee03",
    "1ac2afe07dbdeaf9654d5c661c655040a79b01eea0f815589804f399a953a77d",
    "fa75c75b713ff10bef7096a26d81d030cbd2b829d19cadb6d312c5b1d54abc7d",
    "4ce8cc1c348d6d3902f3efabcf6e54b97bf2a31eecb50e7eeb0e308613eb3212",
    "d8a1d0ad7c3a598f06469cf6de67707625c5caeecac936ab660cd72b738ac523",
    "16742ba1877bf1d8579f9c0bfea080551d75b12ecaa08bd99d7809782576fc21",
    "be7ce54334b75d53412b9c56be22b84a750daa51ef4aaae43a61841bac792970",
    "067e6e6a1f9d30abf360d6f7c29dc95b7479a2d0c5106d0fa6d5857a66d67767",
    "e60b69290b14b327c6c0ad706aac99494cad4b18f0829989e34ba05a4be81247",
    "68adcdc89bafeee7e3ccdd2ec6b909aeddde8c3923d18bb1a9c541c25c727004",
    "7e02623118b42eb8e0c665c000e7dd26a51b34bba7afe8c94b7f44c1818cb432",
    "36bdd808563a7171d1be08b8faaefc7fed517d54a27782e242988cd6dd8a3c26",
    "820e646d59d3a1a08610962b8120090659c9d225f7b34b59827f322f3ba1a031",
    "107f2365c28d48cbe478fef14004d51d08520f3c28142df6611e0869c8454a3f",
    "c21c2030da45fe7a0488c0fef410c7c0e2f71d5f9c3f61c8965c127630a9e250",
    "58cd1c02f4ed3de833f4295c40d4e3b7040ac1b5157d22ae61e55cd175ef1f59",
    "c005bcfff45b2e9ae54fff93261cfd637da8cd2f977902431783dcabb0c05861",
    "206b085a07343a9ba68ef9e9b3aae643184e79459e5c0e0cf5426df189170205",
    "eebcc914c96afdb28a772715c55fb68caf723ea1493795c6226eb0351491563c",
    "54f340f7cde314e3e40d478758a3a62ca66b1fbfc0e36b5d8dd5d5022d88930d",
    "0cf1e0d34b449f966fe91d08c13d85e3e620c58dfed327f88fcc4b21dad2a02c",
    "9edd39021abc2a5ccc2a4c9fe7ee3e870dfdb88af74b3f405171ad0a38a93152",
    "ec7a88ff8da594f1d9f1fdcd060ac64c8ed9b8298c5cf6c8de9a6526a68fd710",
    "ecaef5b2c04d40563fd65c1fa075a7a8260a5836b366170bed5b851f5823eb20",
    "f45f7e0ce5b41812ba174e8d6f59156be87daa2b4a633b70e4d3099098b10a03",
    "dac568b31b0c6a50e163ce4f99cf480ff22162dcd8fee07a93eb004e38ed8b25",
    "4808776f5337a9ad712e8cf5e4875253bad366778418a47a43d549ff4c05f823",
    "76eed0692084cba807d9df4ac6d66e33ed4f134a00b4ae9f7c86cb510c638474",
    "c220722dd8d3b56b7128ae8b2aec00cfbe59eebc0fd69050950fc608f0ae183c",
    "ba8e5bcd59bc6f7a09bf961bdf5348e28484ea31f030d7a9fe8242a978621e06",
    "a6d105d1978086aaa8379f0d7cec698142c29d1bf75ee5dd8261dc2f9534e16d",
    "107aa385525c35a984d2eb95689957b8d203aebb1fcb814b2a06321c20f5351e",
    "ecdb5455953822f02541b96e6ffe035bd7bdbcd0af8ad7c0d2e67504ac68a657",
    "dc5396b89e94fce09eeefc5b22475eec9bc421147151658a7b0c07d420a4ec45",
    "b830083351311355a5f75e39e8307b27787dbad683b00062ed7216128e46c65e",
    "b64e8aac6a7062d88b41ac3dca2a8bb2387c9becba594d62b4106b1231459365",
    "30515d2e3edda1404c8ec535f6cfe5feb7154e52a35e4b9fc7de3cf10d71cb42",
    "dc3739d051fa6421ac4129d3554754e63f20a699a2f0a6bec18e63a8eb26f108",
    "44d204c2578cb087c257f300c38f856aef1c816d26beaf3f0d7b285d12765f79",
    "48c80c43d1fff616e1a57bf8ed88fc141867ebcbc12cfdb05115f1a9b7eef206",
    "6cd301c2a865747f8996b03b7486525a1b20baa0cbc9f744a10f717c5af98771",
    "86e3c3c93e746dfe8cc3c8b5a0cd3006cd2fa227d7c23712fb3eaf3e6186004a",
    "6ee7c9e5307b8e18ffa55dfde94c324f6ff5b10805cbd36ca6b26e2407467869",
    "a80d82e44a51516940ca550c475886f6092bd8e9d558e107443301c5b961da6d",
    "9a2a59ecf387371933da8d1ed6990473425ba5f332c959d26d52b2e50504f10b",
    "d01653f46a7b30504230db5960b13cfabcb88e23ba7f0b4cb6b43851b8e9bc53",
    "a2ea488ad2c4aeb6bf582cacc2465d3333948b0bd899c146339d252897ad255d",
    "70d1e40d504456b52016fd39eeba1b9c91e24785fbd8399adc19b389596b243b",
    "9cb2e9146748e3e94f715e7dce67a2b536c8fec2145cf99b467ff02057bd2101",
    "34df7c166abeffb55dcfe6b93a1ca3a8d9d029384ff5d2cf2bfa2ae07ff60346",
    "a86af95a6014ca104692bfa79dea022a0af2fda3f8c4959fe137e911f6ff607d",
    "fe2d0d7351aeeafcbad3d8b5404554ea5bc5fc3b4a70b55d4733a905af41b05d",
    "26e9fd1bb367a462a0067fdccad383b66f83d00ec6c791f2024ec7a74429f47e",
    "1ac335f1af13dfc894708035ea58b5827b8fc5d468472116aeb5af7467ca1624",
    "9220561ae9956e3adb303c180ef99a0f1ce810dbe1a90357c2dc110542cb5e7b",
    "ea48159abd091c945e514dd149193f9d5b054e37cc34d0d192f69ad126b6b24a",
    "b047b654e16e941e0ffff73eea5b3805bfbd5e22e1df4175dbd8cd31512e880d",
    "8a32518184523165a596dc015b4f8a03e448d1f30d2ac6b9c7c7dc84af223317",
    "00c56d738f363b7dc30c4b92960174c62d70bbc495af347d7e9ac3050641276e",
    "6c4c6128fee7749aed11dc46646b7769af0597c62632613b16a36345fc091839",
    "d4897cdd7485cb46da9f75ff5c80ff43c40aab192fc52a796bed9baee5706a7d",
    "60145cd62f6a56cf36ff09c7416b3a8bad2e9db9b91f811d43748edeaef6b15e",
    "fc9e3ba571f56f34da95f1f36eb3ec861f87ebf2e45968f06efe7a8ff50f8804",
    "fcfc3e8169adb67d10bf43d86287c84a4b1937b7628cceb183d9215602ae9b45",
    "b6d0b42fa99887576a714ab7d10485b8ee007b4c3c66554f66515a412e80e519",
    "90c328fafd3497c1cf03cc997c26ce6f49ae07b7d0935adddae1de2476f39514",
    "f61af1e149b971cbdacb65b04055f02af649106382fb61d162b1d36a7a021673",
    "68c6e6c681bf24ddf21d29eea5741c10c1babe2f1730bccf43b7542e43c76404",
    "6a7b0a9df8c85da60d9744665ffbc4044416cc603544fdc5863e25da87d30f47",
    "465ed473fa2dfb7e9ba3e9dbf82db8992539e887a7d1aacdc5b77a86b52a411f",
    "4e5b7a7c045594363d864e8d5001e56a1a02fd1b3e5e4fd10b772e2b7305076d",
    "e69c2e940e8cf9239bb8367c59be8e36240fb40f021760cd8350695bb7ea145e",
    "82be942ef9a3adbf4823aa208447503fe003085cd10d450f8e16bdc11ac7e84b",
    "40e447f8a2ada71ed44dd9d77f031a2f0189d031c26b3d7799d9d0b031cd4264",
    "4cd16caa2ce22dc443d3b50ab740f16753575c3ede0ae483fdb95b7fdd6c7655",
    "80c6d5b94a7449edc307d29f8826d61b5d94e9527bc03b9a1ea97b6b416a870a",
    "1e8d129bea71134159fa48361ddbc037306ddf2d75fe996d5be4f88b48b65308",
    "50457ef4c6df995da79e51136217d773a3d058b7e636640107481b87976bb001",
    "7ed82aa678b7dc6c5781cfde188f35c328066457e47e8d60cd9d73696f89d532",
    "70366efd23e1cb7b50c53e2ebab4ed93745c67ff679219e5b3ed107e99037d46",
    "d655712d7c165a460095abcce9b90f676808a3ae4649672f5037fd2f330eff71",
    "66a44a392a7d0b1d9ad0fc10864adb0f706b0c5119acf4db5b77ccdef0bcde1e",
    "1803bb6b07df4a6d15ac8a86ad1dd5ad453c82b119c96807c3856f0a4f384553",
    "8a9bf7b871316bba206053b368af7958b18bb36edfd100e9d6f32572ee3c0328",
    "ba1e156cda55d4a049c471d43da79aeed7cb85ad9578f20104d1d4b0400c2625",
    "76b8fb77c05dda6d9f5f14e4c82910337b5039294bba6d4b821e813cb0718059",
    "02cb0ea90a4d7d1c668f3b1f60b30106fdfbbf090917f7440949d121a6d7706e",
    "1e956329961ae294bc91ef229dc19084f0d021c85a49a044008fa906cc07e437",
    "9027b3756b6d902154410cc5117ccc0c602de2b4ecc181da7ccb47c38f5d8977",
    "3c24bdd09104866579cc5fbf46b0473a592b127e14c057282a6c0cf761f2b34e",
    "888dce1c017e0360bbf38d10fd3c4c0fa91feabc21479b9b3e77b0eadac5ac2c",
    "2a408665f4172d25bf0cdf83617eba93469487eb09ef4dfe6d7650c5872ce62e",
    "da24704ee28e65c0d4c33952cef0313fa5eb204a94ec7467ef7c3c355fcb8807",
    "12236a7edf90718b03083da3c392b8db748c6fecda2a4d44811185e1ac7d5b6d",
    "fc3fe03c5353edc15c9a1d014b8c3284ceed4d0ede15ca40050b936e7ab0c110",
    "5c4d1a6052aa89684bfcd16e5723e3fb9b5b31700464f4a08680534de38c846b",
    "d0efe26ff9b93667cfd3878dbce5ca73a19a051d70c2af39086dfd354d4bd547",
    "f4a64cb5b0ca4b40704a7519751bd0e852c38a8e2799530c101706c403fa7552",
    "b23ddf90b3c9746ffb3d4cbc99fc9329d1641082f15e1b064e8cbae21a388e3c",
    "387e3ff694ef9af73b5679447323e95427ba1c958b46ce269490d68545df6454",
    "9c97eb745e2c21baea6687f1e4f120176a4aa9a055cf2c8b37b45b1fb28f8220",
    "8ec8f74e3c7d012361b33ab8d5d1164d3906864555c2350ad9483dd94a657b5a",
    "56528a380049d647cf76a58e72807d009b92503d0075d263f0ebd9606392de0c",
    "38245f257b6f08df6bb3bb3eb6e70a59428c6b52b7e1672e144a1c3bb7119018",
    "0831f2c548b168af877553ad87d7e19556df0a95ec59035f5b98eb52eec8e572",
    "4a1d1d1449c0559deb7806335488d920fd7eb1aaab89e3de36b9f5ab8677ab27",
    "2c96fd0395ea4c2027228b77e0384820f0b3756a445f59cbcc76bcd42ed96d03",
    "f4fb2cdc13583d3d00cce0eba65f069859d26090e3fea13cfe3293745d2b3c34",
    "92efdf5cc3aca5f4891eb5bd908cc3d2328a125bd22db4b3eb2e3019dfc41102",
    "8a049f36faacaee562a36b5c33d5f63bb00d3d079734b19143d18f56f1b8900b",
    "4821db1e0fd3338e095162537fe62ce5d9d7b650dfe2c5e9d1a589feaf042d42",
    "22c8a0a042c1dcdcee4ad543dbafc94d58b5c124f98e2186fac4b94a03bcc07c",
    "0aaed572e73f23fd839e12b5027a35dcfabf074ced496f5c714b257536b52d10",
    "50871c8e24d98e247c4f90cfc72245e51385e87d9fd363eb5b3b58c60ef8674c",
    "9abe7d6768bc6b411440336320c983b853e7b55e273db166582652de3f4cd125",
    "584246225e57d05be27c9269922b4c350e9ed02db3a4936e3b00af094d3d9f56",
    "26c0246f6d061088726946b923fcfef38d870b3134983a35b31338d589b08c65",
    "5256db57ac41b4ba13eea3e026734a218a9c0c2db9498fe8b672191df43cba08",
    "9cf12807dcf1a3afafd95107dfef2888e9638c5553917ed1307b40c1ad551c58",
    "3c312eeacdb13781e8c26d68a1796b59e6e4d3ad2e6f7e47f54e2e5afdd60f0b",
    "70ffaf3605a6f46aab42f51478dae5dcaaeb883c1cbf3d1bb007a6435afbd25e",
    "40b4d739482a1041f3eed7b32a699fe1a5e9bf2680c5edf5234b0c2bcda92320",
    "0658cfc2ee975446f596dfb720bcbb5a814aebd8c420c0383a1740c910ab0519",
    "4ce84b8da095a4a66f5cae6f81a8f81c0b58f246a1db6af668d0cfec18d4ef64",
    "08eedcb8b8eb3d67c94258c3974e0df529195d5b3ca797a2fe54b1a237d56531",
    "4aeaa479e19024fdaee17f8a5338a37dc9fd4d38fa0afa3d2acf433ceca0227c",
    "9ebaa568b9ccdfca9031576bccfc04caa58b79e2f55eef5fb0c516d9bc7c7207",
    "42d239ed26951425c4f4a57fa4ac3daa2218c1a5730f00489150b3dc558c1d31",
    "a281ff7d5b3129bf259344aca7385aea6b0d416e63b1fc1a1c257a96924c7e40",
    "befad6762955397cfa0884b3f4b656bbd6ba6dc93e6015bc767e8df5594e0605",
    "fa9d7f84dd229e44ee3ffeb43c1e640057e1e4aa2ffa9c82fcc6c15e56196a2a",
    "c2dd976deb7b7121c091814855286f76b133d13709ceb13c6c4d01c8e5c2b875",
    "9266ebe4594aa545969db6b308e5bff8fa10e1cd11728286b9b2c36323f22248",
    "0a99a1d6f57bec454697ff0c1b659ac9a8e3eb16a9a450bb095a52dbc0efe611",
    "3e737e929a989eddd0ef7d928399899226198d058756b109f3d347d6fe7ead26",
    "26cebc75df4ded3508470f913eef76dbea25fb8b32b06a7387cfcfdccc0ae013",
    "bc9fbdf2d9c90194cc8b1f2c91c5324b653be3f245af77fc989fd5125f2d1231",
    "8c4b1d7931a7a4be6eedab09db4a7d5fd23d8186ca139abf5bcbce09b6cb1d7a",
    "469388b36edfaba611161567d77ef4ca7309778e96a25f056eed674a9b88302d",
    "f2620d7c514925bfb2bebc4270d55dcaa8393d4d042ca41a6254782c85c9cd31",
    "f2e3f3259b6b156c1437693318a6ba4b7e14b5ff0d42853ecb31937b572c4a07",
    "9001e87b77c0dd99be688efabb71fe564a1d7eba46ffda95ed705744d33c1e3e",
    "52b2d32152920fc1fa4a463f76ede0c424ed5c1458a0f123fcd3359c39006720",
    "dedc88e3de99bff7193800c86d347061f3a5362a3e14936625e8342c716e006f",
    "6c76d2348abedc571ab5bd20dd67a9aac0bc5e37fbb4eb610f209be717962515",
    "302ac39f921dbbd6aaede6a20cff307302f8f281d45d7a0ac528199e841c4e32",
    "682fea659b126f93c001d681fb352e4bb15189fe0e22ebd01d6f7a872a8c8606",
    "e64f97b05a0bc7f42cf3a05ddf10be509995d228b60f8531ed56cd553a0b3e20",
  };
  for( int i=0; i<256; i++ ) {
    fd_hex_decode( buf, fd_rangeproofs_generators_H_compressed[i], 32 );
    fd_ristretto255_point_frombytes( &fd_rangeproofs_generators_H[i], buf );
  }

  char const * header[] = {
    "/* Do NOT modify. This file is auto generated by fd_curve25519_tables. */",
    "",
    "#ifndef HEADER_fd_src_flamenco_runtime_program_zksdk_fd_rangeproofs_h",
    "#error \"Do not include this directly; use fd_rangeproofs.h\"",
    "#endif",
    "",
  };
  for( ulong i=0; i<sizeof(header) / sizeof(char*); i++ ) {
    fprintf( file, "%s\n", header[i]);
  }

  fprintf( file, "/* Pedersen base point for encoding messages to be committed.\n"
         "   This is the ed25519/ristretto255 basepoint. */\n");
  ristretto_points_array( file, "fd_rangeproofs_basepoint_G", fd_rangeproofs_basepoint_G, 1 );

  fprintf( file, "/* Pedersen base point for encoding the commitment openings.\n"
         "   This is the hash-to-ristretto of sha3-512(G), with G in compressed form. */\n");
  ristretto_points_array( file, "fd_rangeproofs_basepoint_H", fd_rangeproofs_basepoint_H, 1 );

  fprintf( file, "/* Pedersen generators, aka Gs. Table with first 256 elements. */\n");
  ristretto_points_array( file, "fd_rangeproofs_generators_G", fd_rangeproofs_generators_G, 256 );

  fprintf( file, "/* rangeproofs generators, aka Hs. Table with first 256 elements. */\n");
  ristretto_points_array( file, "fd_rangeproofs_generators_H", fd_rangeproofs_generators_H, 256 );
}

int
main( int     argc,
      char ** argv ) {
  fd_boot( &argc, &argv );
  char path[256];

#if FD_HAS_AVX512
  char const * path_suffix = "avx512";
#else
  char const * path_suffix = "ref";
#endif

  char const * default_dir = "./src/ballet/ed25519/table";
  char const * dir = fd_env_strip_cmdline_cstr( &argc, &argv, "--dir", NULL, NULL );

  if( !dir ) {
    dir = default_dir;
  }


  FD_LOG_NOTICE(( "Saving tables" ));

  {
    snprintf( path, 256, "%s/fd_f25519_table_%s.c", dir, path_suffix );
#if STDOUT
    snprintf( path, 256, "/dev/stdout" );
#endif
    FILE * file = fopen( path, "wb" );
    if( FD_UNLIKELY( !file ) ) FD_LOG_ERR(( "fopen failed: %s", path ));

    field_tables_file( file );

    if( FD_UNLIKELY( fclose( file ) ) ) FD_LOG_WARNING(( "fclose failed; attempting to continue" ));
  }
  {
    snprintf( path, 256, "%s/fd_curve25519_table_%s.c", dir, path_suffix );
#if STDOUT
    snprintf( path, 256, "/dev/stdout" );
#endif
    FILE * file = fopen( path, "wb" );
    if( FD_UNLIKELY( !file ) ) FD_LOG_ERR(( "fopen failed: %s", path ));

    point_tables_file( file );

    if( FD_UNLIKELY( fclose( file ) ) ) FD_LOG_WARNING(( "fclose failed; attempting to continue" ));
  }
  {
    snprintf( path, 256, "%s/fd_rangeproofs_table_%s.c", dir, path_suffix );
#if STDOUT
    snprintf( path, 256, "/dev/stdout" );
#endif
    FILE * file = fopen( path, "wb" );
    if( FD_UNLIKELY( !file ) ) FD_LOG_ERR(( "fopen failed: %s", path ));

    rangeproofs_tables_file( file );

    if( FD_UNLIKELY( fclose( file ) ) ) FD_LOG_WARNING(( "fclose failed; attempting to continue" ));
  }

  FD_LOG_NOTICE(( "pass" ));

  fd_halt();
  return 0;
}
